import asyncio
import logging
from datetime import datetime, date, timedelta
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.interval import IntervalTrigger
from apscheduler.triggers.cron import CronTrigger
from sqlmodel import Session, select, func
from .db import engine, get_session
from .models import Rate
from .datasources.manager import DataSourceManager
from .policies.evaluator import PolicyEvaluator

logger = logging.getLogger(__name__)


class RateScheduler:
    """汇率数据调度器"""
    
    def __init__(self):
        self.scheduler = AsyncIOScheduler()
        self.data_manager = DataSourceManager()
        self.is_initialized = False
    
    async def initialize(self):
        """初始化：检查是否需要拉取历史数据"""
        try:
            with Session(engine) as session:
                # 检查是否有数据
                count_stmt = select(func.count(Rate.id))
                count = session.exec(count_stmt).first()
                
                if count == 0:
                    logger.info("数据库为空，开始拉取30天历史数据")
                    await self._fetch_historical_data()
                else:
                    logger.info(f"数据库已有 {count} 条汇率数据")
                
                self.is_initialized = True
                logger.info("调度器初始化完成")
                
        except Exception as e:
            logger.error(f"调度器初始化失败: {e}")
            raise
    
    async def _fetch_historical_data(self):
        """拉取30天历史数据"""
        try:
            end_date = date.today()
            start_date = end_date - timedelta(days=30)
            
            logger.info(f"拉取历史数据: {start_date} 到 {end_date}")
            
            # 获取历史数据
            historical_data = await self.data_manager.get_historical_rates(
                base="JPY",
                quotes=["CNY", "USD"],
                start_date=start_date,
                end_date=end_date
            )
            
            # 写入数据库
            with Session(engine) as session:
                for rate_data in historical_data:
                    rate = Rate(
                        ts_utc=rate_data.timestamp,
                        base=rate_data.base,
                        quote=rate_data.quote,
                        rate=rate_data.rate
                    )
                    session.add(rate)
                
                session.commit()
                logger.info(f"成功写入 {len(historical_data)} 条历史数据")
                
        except Exception as e:
            logger.error(f"拉取历史数据失败: {e}")
            raise
    
    async def _fetch_latest_rates(self):
        """拉取最新汇率数据"""
        try:
            logger.info("开始拉取最新汇率数据")
            
            # 获取最新数据
            latest_data = await self.data_manager.get_latest_rates(
                base="JPY",
                quotes=["CNY", "USD"]
            )
            
            # 写入数据库（去重）
            with Session(engine) as session:
                for rate_data in latest_data:
                    # 检查是否已存在（基于时间戳和货币对）
                    existing_stmt = select(Rate).where(
                        Rate.ts_utc == rate_data.timestamp,
                        Rate.base == rate_data.base,
                        Rate.quote == rate_data.quote
                    )
                    existing = session.exec(existing_stmt).first()
                    
                    if not existing:
                        rate = Rate(
                            ts_utc=rate_data.timestamp,
                            base=rate_data.base,
                            quote=rate_data.quote,
                            rate=rate_data.rate
                        )
                        session.add(rate)
                        logger.info(f"新增汇率数据: {rate_data.base}→{rate_data.quote} = {rate_data.rate}")
                    else:
                        logger.debug(f"汇率数据已存在，跳过: {rate_data.base}→{rate_data.quote}")
                
                session.commit()
                
                # 执行策略评估
                await self._evaluate_policies()
                
        except Exception as e:
            logger.error(f"拉取最新汇率数据失败: {e}")
    
    async def _evaluate_policies(self):
        """执行策略评估"""
        try:
            with Session(engine) as session:
                evaluator = PolicyEvaluator(session)
                triggered_count = await evaluator.evaluate_all_rules()
                
                if triggered_count > 0:
                    logger.info(f"策略评估完成，触发 {triggered_count} 条规则")
                else:
                    logger.debug("策略评估完成，无规则触发")
                    
        except Exception as e:
            logger.error(f"策略评估失败: {e}")
    
    async def _cleanup_old_data(self):
        """清理超过30天的历史数据"""
        try:
            logger.info("开始清理超过30天的历史数据")
            
            with Session(engine) as session:
                # 删除30天前的数据
                cutoff_date = datetime.now() - timedelta(days=30)
                delete_stmt = select(Rate).where(Rate.ts_utc < cutoff_date)
                old_rates = session.exec(delete_stmt).all()
                
                for rate in old_rates:
                    session.delete(rate)
                
                session.commit()
                deleted_count = len(old_rates)
                logger.info(f"清理完成，删除了 {deleted_count} 条历史数据")
                
        except Exception as e:
            logger.error(f"清理历史数据失败: {e}")
    
    def start_scheduler(self):
        """启动调度器"""
        if not self.is_initialized:
            logger.error("调度器未初始化，无法启动")
            return
        
        # 每30分钟拉取最新汇率
        self.scheduler.add_job(
            self._fetch_latest_rates,
            trigger=IntervalTrigger(minutes=30),
            id="fetch_latest_rates",
            name="拉取最新汇率",
            max_instances=1,
            replace_existing=True
        )
        
        # 每周日8:00清理历史数据
        self.scheduler.add_job(
            self._cleanup_old_data,
            trigger=CronTrigger(day_of_week=6, hour=8, minute=0),  # 周日8:00
            id="cleanup_old_data",
            name="清理历史数据",
            max_instances=1,
            replace_existing=True
        )
        
        self.scheduler.start()
        logger.info("调度器已启动")
        logger.info("  - 每30分钟拉取最新汇率")
        logger.info("  - 每周日8:00清理历史数据")
    
    def stop_scheduler(self):
        """停止调度器"""
        if self.scheduler.running:
            self.scheduler.shutdown()
            logger.info("调度器已停止")
    
    async def manual_trigger_fetch(self):
        """手动触发拉取（用于API调用）"""
        await self._fetch_latest_rates()
    
    async def manual_trigger_eval(self):
        """手动触发策略评估（用于API调用）"""
        await self._evaluate_policies()
